/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.submit;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import net.bioteam.appweb.Config;
import net.bioteam.common.utils.MyEntityManager;
import net.bioteam.common.utils.Utils;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class BaseCommandSubmitter implements CommandSubmitter
{
	public static final Log logger=LogFactory.getLog(BaseCommandSubmitter.class);
	public static Random random = new Random(System.currentTimeMillis());
	
	

	public UnfinishedJob saveJobInfo(SubmitData data) throws Exception
	{
		StringBuffer sb = new StringBuffer();
		Formatter formatter = new Formatter(sb);
		Date date = new Date();
		formatter.format("_%tY%tm%td_%tH%tM%tS", date, date, date, date, date, date);
		File file = new File(Config.topWorkdir + File.separator + data.getUser().getName() + File.separator + data.getProgram().getName() + "_" + sb.toString());

		if (file.exists())
		{
			sb = new StringBuffer();
			formatter = new Formatter(sb);
			formatter.format("_%tY%tm%td_%tH%tM%tS_%tL", date, date, date, date, date, date, date);
			file = new File(Config.topWorkdir + File.separator + data.getUser().getName() + File.separator + data.getProgram().getName() + "_" + sb.toString());
		}
		if (!file.mkdirs())
		{
			throw new SubmitException("can not make directory " + file.getAbsolutePath());	
		}

		try
		{

			// add the default value for meta data entry which is not displayed.
			for (net.bioteam.appweb.model.meta.Entry entry : data.getProgram().getMetaData().values())
			{
				if ((!entry.isDisplay()) && entry.getValue() != null && (!data.getBean().getValueMap().containsKey(entry.getName())))
				{
					data.getBean().getValueMap().put(entry.getName(), entry.getValue());
				}
			}
			// copy file
			for (Map.Entry<String, String> entry : data.getBean().getValueMap().entrySet())
			{
				// copy or move file.
				if (isUserTmpFile(entry.getValue()))
				{
					File tempFile = new File(entry.getValue());
					File targetFile = new File(file.getAbsolutePath() + File.separator + tempFile.getName());
					FileUtils.moveFile(tempFile, targetFile);
					data.getBean().setValue(entry.getKey(), targetFile.getAbsolutePath());
				} else if (isUserServerFile(entry.getValue()))
				{
					File tempFile = new File(entry.getValue());
					File targetFile = new File(file.getAbsolutePath() + File.separator + tempFile.getName());
					FileUtils.copyFile(tempFile, targetFile);
					data.getBean().setValue(entry.getKey(), targetFile.getAbsolutePath());
				}
			}
			generateParameterFile(file, PROP_NAME, data);
		} catch (Exception e)
		{
			// recursive deletion.
			FileUtils.deleteDirectory(file);
			throw e;
		}

		data.setWorkdir(file);
		
		UnfinishedJob rs=new UnfinishedJob();
		if (data.Bean.getValue(Config.EMAIL_KEY) != null && data.Bean.getValue(Config.EMAIL_KEY).trim().length()>0)
		{
			rs.setEmail(data.Bean.getValue(Config.EMAIL_KEY));
		} else
		{
			rs.setEmail(data.getUser().getEmail());
		}
		rs.setPreSubmitTime(new Date());
		rs.setProgramName(data.Bean.getProgram().getName());
		rs.setUsername(String.valueOf(data.getUser().getUserid()));
		rs.setWorkdir(data.getWorkdir().getAbsolutePath());
		rs.setCode(RunStatusCode.PRESUBMIT);
		rs.setClusterid(Long.parseLong(data.Bean.getValue(Config.CLUSTER_KEY)));
		rs.setNote("Pending for Submission");
		rs.setTrials(0);
		
		EntityManager em = MyEntityManager.getEntityManager();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		em.persist(rs);
		tx.commit();
		
		return rs;
	}

	private String generateParameterFile(File dir, String name, SubmitData data) throws IOException
	{
		String fileName = dir.getAbsolutePath() + File.separator + name;
		Map<String, String> outMap = new HashMap<String, String>(data.Bean.getValueMap());
		outMap.put(SUBMIT_SOURCE, data.getSubmitSource().toString());
		if (data.serviceID != null)
		{
			outMap.put(SERVICE_ID, data.serviceID);
		}
		XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(fileName)));
		e.writeObject(outMap);
		e.close();
		return fileName;
	}

	public static Map<String, String> getProperties(File dir) throws FileNotFoundException
	{
		String filename = dir.getAbsolutePath() + File.separator + PROP_NAME;
		XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream(filename)));
		Map<String, String> outMap = (Map<String, String>) d.readObject();
		d.close();
		return outMap;
	}

	public static boolean isUserTmpFile(String filepath)
	{
		return FilenameUtils.separatorsToSystem(filepath).startsWith(FilenameUtils.separatorsToSystem(Config.USER_TMP));
	}

	public static boolean isUserServerFile(String filepath)
	{
		return FilenameUtils.separatorsToSystem(filepath).startsWith(FilenameUtils.separatorsToSystem(Config.USER_FILE));
	}
	
}
